package com.jia.train.seat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jia.train.global.page.PageResponse;
import com.jia.train.global.utils.SnowIdUtil;
import com.jia.train.seat.entity.TrainCarriage;
import com.jia.train.seat.entity.TrainSeat;
import com.jia.train.seat.entity.TrainSeatExample;
import com.jia.train.seat.enums.SeatColEnum;
import com.jia.train.seat.mapper.TrainSeatMapper;
import com.jia.train.seat.request.GeneratorSeatRequest;
import com.jia.train.seat.request.TrainSeatQueryRequest;
import com.jia.train.seat.request.TrainSeatSaveRequest;
import com.jia.train.seat.response.TrainSeatQueryResponse;
import com.jia.train.seat.response.TrainSeatSaveResponse;
import com.jia.train.seat.service.TrainCarriageService;
import com.jia.train.seat.service.TrainSeatService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class TrainSeatServiceImpl implements TrainSeatService {

    @Resource
    private TrainSeatMapper trainSeatMapper;
    // 编程式事务
    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private TrainCarriageService trainCarriageService;

    public static final Logger logger = LoggerFactory.getLogger(TrainSeatServiceImpl.class);


    @Override
    public TrainSeatSaveResponse insert(TrainSeatSaveRequest request) {
        TrainSeat trainSeat = BeanUtil.copyProperties(request, TrainSeat.class);
        DateTime now = DateTime.now();
        if (ObjectUtil.isEmpty(trainSeat.getId())) {
            trainSeat.setId(SnowIdUtil.getLongSnowNextId());
            trainSeat.setCreateTime(now);
            trainSeatMapper.insert(trainSeat);
        } else {
            trainSeat.setUpdateTime(now);
            trainSeatMapper.updateByPrimaryKeySelective(trainSeat);
        }

        return BeanUtil.copyProperties(trainSeat, TrainSeatSaveResponse.class);
    }

    @Override
    public PageResponse<TrainSeatQueryResponse> selectPage(TrainSeatQueryRequest request) {

        TrainSeatExample trainSeatExample = new TrainSeatExample();
        // 排序
        trainSeatExample.setOrderByClause("trip_code asc,`carriage_index` asc,carriage_seat_index asc");
        // 条件
        TrainSeatExample.Criteria criteria = trainSeatExample.createCriteria();
        String tripCode = request.getTripCode();
        if (StringUtils.hasText(tripCode)) {
            criteria.andTripCodeEqualTo(tripCode);
        }

        // 构造分页
        PageHelper.startPage(request.getPage(), request.getSize());
        List<TrainSeat> trainSeats = trainSeatMapper.selectByExample(trainSeatExample);
        PageInfo<TrainSeat> pageInfo = new PageInfo<>(trainSeats);

        List<TrainSeatQueryResponse> list
                = BeanUtil.copyToList(trainSeats, TrainSeatQueryResponse.class);

        PageResponse<TrainSeatQueryResponse> pageResponse = new PageResponse<>();
        pageResponse.setTotal(pageInfo.getTotal());
        pageResponse.setList(list);
        return pageResponse;
    }

    @Override
    public void deleteTrainSeat(Long id) {
        trainSeatMapper.deleteByPrimaryKey(id);
    }

    @Override
    public Integer generatorSeat(GeneratorSeatRequest request) {

        StopWatch stopWatch = new StopWatch();

        TrainSeatExample trainSeatExample = new TrainSeatExample();
        String tripCode = request.getTripCode();
        trainSeatExample.createCriteria().andTripCodeEqualTo(tripCode);

        DateTime now = DateTime.now();

        stopWatch.start();

        // 查询当前车次 的车厢 座位类型
        List<TrainCarriage> trainCarriages
                = trainCarriageService.selectAllByTripCode(tripCode);

        // 循环生成座位 TODO 数组给个默认值 700
        List<TrainSeat> trainSeatList = new ArrayList<>(700);
        TrainSeat trainSeat;

        for (TrainCarriage trainCarriage : trainCarriages) {
            // 行数
            Integer rowCount = trainCarriage.getRowCount();
            String seatType = trainCarriage.getSeatType();
            int count = 1;
            List<SeatColEnum> colsEnumList = SeatColEnum.getColsByType(seatType);
            // 排数
            for (int i = 1; i <= rowCount; i++) {
                // 列数
                for (SeatColEnum seatColEnum : colsEnumList) {
                    trainSeat = new TrainSeat();
                    trainSeat.setId(SnowIdUtil.getLongSnowNextId());
                    trainSeat.setTripCode(tripCode);
                    trainSeat.setCarriageIndex(trainCarriage.getIndex());
                    trainSeat.setRow(String.valueOf(i));
                    trainSeat.setCol(seatColEnum.getCode());
                    trainSeat.setCarriageSeatIndex(count++);
                    trainSeat.setSeatType(seatType);
                    trainSeat.setCreateTime(now);
                    trainSeatList.add(trainSeat);
                }
            }
        }

        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);

        transactionTemplate.executeWithoutResult(status -> {
            try {
                // 重复的处理逻辑 1.直接跳过 2.删除之前生成的数据
                trainSeatMapper.deleteByExample(trainSeatExample);

                List<List<?>> lists = splitList(trainSeatList);
                for (List<?> list : lists) {
                    trainSeatMapper.batchInsert(list);
                }
            } catch (Exception e) {
                status.setRollbackOnly();
                throw new RuntimeException(e.getMessage());
            }
        });

        stopWatch.stop();
        logger.info("本次生成座位耗时：{}s", stopWatch.getTotalTimeSeconds());

        return 0;
    }

    /**
     * 三分数组
     *
     * @param splitList 数组
     * @return 数组
     */
    public List<List<?>> splitList(List<?> splitList) {
        Assert.noNullElements(splitList, "Arrays cannot be empty");
        int size = splitList.size();
        List<List<?>> resultList = new ArrayList<>(3);
        if (size <= 3) {
            return Collections.singletonList(splitList);
        }
        int start = size / 3;
        List<?> part1 = splitList.subList(0, start);
        resultList.add(part1);
        List<?> part2 = splitList.subList(start, Math.min(2 * start, size));
        resultList.add(part2);
        List<?> part3 = splitList.subList(start * 2, size);
        resultList.add(part3);
        return resultList;
    }
}
